/* Initial beliefs and rules */

//Tout cuisinier commence 'enAttente'
cuisinierDisponible.


/* Initial goals */

!start.

/* Plans */

+!start : true <- 	enregistreCuisinier(1).

+selfCuisinier(Cuisinier) <- +quantiteDePlats(Cuisinier,0); .print("Cuisinier ",Cuisinier," enregistre").

//Seullement un chef recoi une commande! Cuisinier recoi PLAT
//+commandeAPreparer(Commande,Cuisinier)  <- 	.print("Le cuisinier", Cuisinier, " a recu la commande ", Commande).



//******** Debut des actions des CUISINIERS. Les CHEFS seront faites apres ********

//Si le cuisinier n'as rien a faire, demande une attribuition au Chef
+cuisinierDisponible : fonction(Chef,chef) & selfCuisinier(Cuisinier) & copain(Cuisinier,Chef)  <- !demandeAttribuitionAuChef(Chef,Cuisinier).
//ca permet de forcer qu'une commande soit faite meme si ce n'est pas la specialite du cuisinier

+!demandeAttribuitionAuChef(Chef,Cuisinier) : selfCuisinier(Cuisinier) <- .send(Chef,tell, cuisineirDisponible(Cuisinier,Chef));
.print("Cuisinier ",Cuisinier," demande attribution au chef ",Chef).


//Si il recoit une attribuition et il est libre (moins de 4 plats) enregistre et l'ajoute a table devant lui 
//X: Cuisinier, Y: Plat, W: chef OU copain
+recuAttribuition(Cuisinier,Plat,TypePlat,Chef,Commande,PositionTable): true <- !decideQuoiFaireAvecAttribution(Cuisinier,Plat,TypePlat,Chef,Commande,PositionTable).

+!decideQuoiFaireAvecAttribution(Cuisinier,Plat,TypePlat,Chef,Commande,PositionTable):   selfCuisinier(Cuisinier) &quantiteDePlats(Cuisinier,QuantiteDePlats) & cuisinierDisponible <-  
-recuAttribuition(Cuisinier,Plat,TypePlat,Chef,Commande,PositionTable);
+quantiteDePlats(Cuisinier, QuantiteDePlats+1);
+platAttribue(Plat,Cuisinier,Commande,PositionTable);
.print("Plat ",Plat," attribuee au cuisinier ",Cuisinier);
.print("Le cuisinier ", Cuisinier, " a recu la commande ", Commande);
platAttribue(Plat,Cuisinier,Commande,PositionTable);
!cuisinePlat(Cuisinier, Plat,TypePlat, Chef, Commande,PositionTable).


//Si il est occupe avec 4 commandes, il se met indisponible
+quantiteDePlats(Cuisinier, QuantiteDePlats) : selfCuisinier(Cuisinier) & (QuantiteDePlats<4)& not cuisinierDisponible<- +cuisinierDisponible;
.print("Le cuisinier ", Cuisinier, " est devenu disponible").
+quantiteDePlats(Cuisinier, QuantiteDePlats) : selfCuisinier(Cuisinier) & (QuantiteDePlats==4)&cuisinierDisponible <- -cuisinierDisponible;
.print("Le cuisinier ", Cuisinier, " est devenu indisponible").

//Si il recoit une commande d'un chef et est indisponible, essaye de passer a son copain (reseaux sociaux)
+!decideQuoiFaireAvecAttribution(Cuisinier,Plat,TypePlat,Chef,Commande,PositionTable): selfCuisinier(Cuisinier) & not cuisinierDisponible <- 
!demandeAuCopain(Cuisinier,Plat,Chef,Commande,PositionTable);
.print("Le cuisinier ",C," ne peut pas faire le plat ",Y);
.print("Il demande aux autres cuisiniers").
//.wait(1000).

//La fonction enregistreCuisinier va donner les copains: X cuisinier, Y Plat, W Chef, Z Copain
+!demandeAuCopain(Cuisinier,Plat,Chef,Commande,PositionTable) : selfCuisinier(Cuisinier) & copain(Cuisinier,Copain) &  not fonction(Copain,chef) <- 
.send(Copain,tell, besoin(Copain,Plat,Cuisinier,Chef,Commande,PositionTable));
.print("Le cuisinier ",Cuisinier," a demande au copain ",Copain," de faire le plat ", Plat).

//dit au chef W qui va faire le plat:
+besoin(Copain,Plat,Cuisinier,Chef,Commande,PositionTable) : selfCuisinier(Copain) & cuisinierDisponible <- 
+recuAttribuition(Copain,Plat,Cuisinier,Commande,PositionTable);
.send(Chef,tell,nouvelleAttribuition(Plat,Copain,Cuisinier,Commande,PositionTable));
.send(Cuisinier,untell,recuAttribuition(Cuisinier,Plat,Chef,Commande,PositionTable));
.print("Le copain ",Copain," a pris le plat ",Plat, " et a dis au Chef ",Chef).

//il ne peut pas prendre l'attribuition de son amie.															
+besoin(Copain,Plat,Cuisinier,Chef,Commande,PositionTable) : selfCuisinier(Copain) & not cuisinierDisponible <- 
.send(Cuisinier,tell,copainIndisponible(Plat,Copain,Cuisinier,Chef,Commande,PositionTable));
.print("Le copain ",Copain," ne peut pas faire le plat ",Plat).

//Pendant l'echange de messages, le cuisinier initial est devenu disponible
+copainIndisponible(Plat,Copain,Cuisinier,Chef,Commande,PositionTable) :  selfCuisinier(Cuisinier) & cuisinierDisponible <- 
+recuAttribuition(Cuisinier,Plat,Chef,Commande,PositionTable);
.print("Avec le copain ",Copain," indisponible, ",Cuisinier," vas faire le plat ",Plat).

//X n'a pas pu faire une fois, a demande au copain qui ne pouvait non plus et X a reessaye, sans succes. Attribuition annullee!
+copainIndisponible(Plat,Copain,Cuisinier,Chef,Commande,PositionTable) : selfCuisinier(Cuisinier) & not cuisinierDisponible <- 
.send(Chef,tell,attribuitionAnnullee(Plat,Cuisinier,Chef,Commande,PositionTable));
.print("Personne ne peut faire le plat ",Plat," alors l'attribuition est annulee pour le chef ",Chef).

//******** Actions de preparation de plats: ********

//Si l'action du cuisinier X est la meme qui le plat Y, ajoute qualite, sinon, le plat est mauvais
// ca change la fonction du client (rouge, jaune,vert)


//Si il vient de finir une commande, enleve de la base de connaissances et se met disponible
//en plus, ajoute le plat a table (guichet) devant lui
+!cuisinePlat(Cuisinier,Plat,TypePlat, Chef,Commande,PositionTable) : selfCuisinier(Cuisinier) & specialite(Cuisinier,TypePlat) <- defineQualite(Plat, bonne);
preparePlat(Cuisinier,Plat, Chef,Commande,PositionTable);
!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable);
.print("La qualite du plat ",Plat," sera SUPER parce que ",Cuisinier, " est le meilleur!");
!appelChef(Cuisinier,Plat,Chef,Commande,PositionTable) .

+!cuisinePlat(Cuisinier,Plat,TypePlat, Chef,Commande,PositionTable) : selfCuisinier(Cuisinier) & not specialite(Cuisinier,TypePlat) <- defineQualite(Plat, moyenne);
preparePlat(Cuisinier,Plat, Chef,Commande,PositionTable);
!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable);
.print("La qualite du plat ",Plat," sera moyenne parce que ce n'est pas la specialite de ",Cuisine);
!appelChef(Cuisinier,Plat,Chef,Commande,PositionTable) .

//Prepare dessert, pendant 3 tourns																
+!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable) : selfCuisinier(Cuisinier) & (TypePlat==dessert) & not platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable,Tourns)<- 
+platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable, 3);
!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable).

+!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable) : selfCuisinier(Cuisinier) & (TypePlat==dessert) & platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable,Tourns) & not (Tourns==0)<- 
-platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable, Tourns);
+platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable, Tourns-1);
.print("Il manque encore ",Tourns-1," tourns pour le dessert ",Plat, " de la commande ", Commande, " devenir pret pour le cuisinier ",Cuisinier );
.wait(1000);
!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable).

+!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable) : selfCuisinier(Cuisinier) & (TypePlat==dessert) & platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable,0)<- 
-platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable, Tourns);
+platFinit(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable);
.print("Le dessert ",Plat, " de la commande ", Commande, " est finit pour le cuisinier ",Cuisinier ).																	

//Prepare entree, pendant 2 tourns																
+!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable) : selfCuisinier(Cuisinier) & (TypePlat==entree) & not platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable,Tourns)<- 
+platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable, 2);
!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable).

+!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable) : selfCuisinier(Cuisinier) & (TypePlat==entree) & platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable,Tourns) & not (Tourns==0)<- 
-platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable, Tourns);
+platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable, Tourns-1);
.print("Il manque encore ",Tourns-1," tourns pour l'entree ",Plat, " de la commande ", Commande, " devenir pret pour le cuisinier ",Cuisinier );
.wait(1000);
!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable).

+!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable) : selfCuisinier(Cuisinier) & (TypePlat==entree) & platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable,0)<- 
-platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable, Tourns);
+platFinit(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable);
.print("L'entree",Plat, " de la commande ", Commande, " est finit pour le cuisinier ",Cuisinier ).																


//Prepare plat principal, pendant 5 tourns																
+!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable) : selfCuisinier(Cuisinier) & (TypePlat==plat) & not platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable,Tourns)<- 
+platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable, 5);
!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable).

+!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable) : selfCuisinier(Cuisinier) & (TypePlat==plat) & platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable,Tourns) & not (Tourns==0)<- 
-platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable, Tourns);
+platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable, Tourns-1);
.print("Il manque encore ",Tourns-1," tourns pour le plat ",Plat, " de la commande ", Commande, " devenir pret pour le cuisinier ",Cuisinier );																	
.wait(1000);
!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable).

+!preparePlat(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable) : selfCuisinier(Cuisinier) & (TypePlat==plat) & platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable,0)<- 
-platEnCours(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable, Tourns);
+platFinit(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable);
.print("Le plat ",Plat, " de la commande ", Commande, " est finit pour le cuisinier ",Cuisinier ).																	




//Appel le chef pour dire qui est finit																	
+!appelChef(Cuisinier,Plat,Chef,Commande,PositionTable) : selfCuisinier(Cuisinier) & quantiteDePlats(Cuisinier,QuantiteDePlat)& platFinit(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable) <- 
-quantiteDePlats(Cuisinier,QuantiteDePlat);
+quantiteDePlats(Cuisinier,QuantiteDePlat-1);
-platFinit(Cuisinier,Plat, Chef,Commande,TypePlat,PositionTable);
.print("Cuisinier ",Cuisinier," a finit le plat:",Plat," pour le chef ",Chef);
platTermine(Cuisinier,Plat,Commande,PositionTable);
.send(Chef,tell,platFini(Cuisinier,Plat,Chef,Commande,PositionTable)).
//!regardeSesPropresAttributions(Cuisinier).



//Loop pour cuisinier tous les plats qui ne sont pas encore prets:




